package main

import (
	"bytes"
	"crypto/sha256"
	"encoding/binary"
	"encoding/gob"
	"log"
	"time"
)

//Block 区块结构
type Block struct {
	Data      string //交易数据
	Timestamp int64  //时间戳
	PrevHash  []byte //前块hash
	Hash      []byte //当前块hash
}

//Int2Hex 将整型数转成切片
func Int2Hex(data int64) []byte {
	//这个机构提封装了write方法，指挥writer接口
	//现实中，数据存储到内存的方式一共有2种，
	var buf bytes.Buffer

	err := binary.Write(&buf, binary.BigEndian, data)
	if err != nil {
		log.Panic("failed to binary.Write", err)
	}
	return buf.Bytes()
}

//NewBlock 构造函数
func NewBlock(data string, prevHash []byte) *Block {
	//生成一个区块，需要先计算一个hash
	//得到一个int64类型的时间戳
	//time.Now().Unix()
	//Join(s [][]byte, sep []byte) []byte
	//sep 的作用是将s组合的切片进行分割
	header := bytes.Join(
		[][]byte{[]byte(data), Int2Hex(time.Now().Unix()), prevHash},
		[]byte{},
	)
	hash := sha256.Sum256(header)
	return &Block{
		data,
		time.Now().Unix(),
		prevHash,
		hash[:],
	}

}

//NewGenesisBlock 创建创世块
func NewGenesisBlock() *Block{
	return NewBlock("The genesis block",[]byte{})
}

//Serialize 编码器
func (b *Block) Serialize() []byte{
	var buf bytes.Buffer //buffer封装了write方法，所以支持writer接口
	//NewDecoder(r io.Reader) *Decoder
	encoder :=gob.NewEncoder(&buf)
	err :=encoder.Encode(b)
	if err !=nil{
		log.Panic("Failed to Encode",err)
	}
	return buf.Bytes()
}

//DeSerialize 将区块信息反序列化
func DeSerialize(data []byte) *Block{
	var block Block
	//生成decoder
	//func NewDecoder(r io.Reader) *Decoder
	//func bytes.NewReader(b []byte) *Reader
	decoder :=gob.NewDecoder(bytes.NewReader(data))
	err :=decoder.Decode(&block)
	if err !=nil{
		log.Panic("Failed to Encode",err)
	}
	return &block
}